import { HYEventStore } from 'hy-event-store'
import { getSongDetail } from '../service/api_music'
import { getSongLyric } from '../service/api_music'
// 全局唯一播放器
const audioContext = wx.getBackgroundAudioManager()

const playerStore = new HYEventStore({
  // 数据状态
  state: {
    // id
    id: 0,
    // 播放总时间
    durationTime: 0,
    // 当前时间
    currentTime: 0,
    // 歌曲列表
    songList: [],
    songIndex: 0, //歌曲列表的第index首歌
    // 当前歌曲信息
    songData: {},
    // 播放状态
    playerState: true,
    // 进度条的数值
    sliderValue: 0,
    // 是否为第一次播放
    isFirstPlay: true,
    // 播放模式 0:循环播放 1:单曲循环 2:随机播放
    playerMode: 0,
    // 歌词信息
    lyric: [],
    lyricIndex: 0,
  },
  actions: {
    // 初始化点开歌曲
    initSong(ctx, id) {
      // 0.如果id一样，说明是同一首歌，不用重置，但是要判断并变换歌词位置，因为可能在外部播放了一段时间，歌词要直接跳到对应的地方
      if(id == ctx.id) {
        this.dispatch("changeProgress")
        return
      } 
      ctx.id = id
      // 1.重置播放歌曲
      this.dispatch("resetMessage", id)
      // 2.获取歌曲数据
      getSongDetail(id).then(res => {
        ctx.songData = res.songs[0]
        audioContext.title = ctx.songData.name
      })
      // 3.监听播放器的各种数据变化
      this.dispatch("spyAudioData")
      // 4.获取歌词信息
      this.dispatch("processLyricFun", id)
      
      // 
    },
    // 调用歌词函数
    processLyricFun(ctx, id) {
      getSongLyric(id).then(res => {
        // 将返回结果的字符串进行处理->歌词处理
        if(res.lrc) {
          this.dispatch("processLyric", res.lrc.lyric)
        }
      })
    },
    // 处理歌词
    processLyric(ctx, lyric) {
      // 0.定义好临时的歌词数组，当处理完成后直接赋值即可
      let lyricResult = []
      // 1.设置歌词的文字匹配模式，其中小括号内为需要匹配的内容
      const pattern = /\[(\d{2}):(\d{2})\.(\d{2,3})\]/
      // 2.由于原始歌词数据会根据每行进行换行，因此可以将一整个字符串变换为歌词字符串数组
      const lyricArr = lyric.split("\n")
      // 3.循环匹配，计算出对应的时间
      for(let lyricLine of lyricArr) {
        // 3.1 获取匹配时间的结果数组，如果没有匹配结果，就跳过
        const timeResult = pattern.exec(lyricLine)
        if(!timeResult) continue
        // 3.2 将分钟和秒钟转换成毫秒，才好匹配
        const minute = parseInt(timeResult[1]) * 60 * 1000
        const second = parseInt(timeResult[2]) * 1000
        // 3.3 得到最后的时间
        const finalTime = minute + second
        // 3.4 得到时间后面的歌词---将匹配模式中的所有内容，直接变为空字符串，去除两边空格，如果最后结果为空字符串，跳过
        const lyricText = lyricLine.replace(pattern, "").trim()
        if(lyricText == '') continue
        // 3.5 将以上两个数据抽成对象，最后全部加入数组当中
        const obj = {
          time: finalTime,
          text: lyricText 
        }
        lyricResult.push(obj)
      }
      // 4.更新歌词数据
      ctx.lyric = lyricResult
    },
    
    // 重置信息
    resetMessage(ctx, id) {
      audioContext.src = `https://music.163.com/song/media/outer/url?id=${id}.mp3`
      audioContext.title = id
      audioContext.onCanplay(() => {
        audioContext.play()
        ctx.playerState = true
        // 得到的是秒，要转成毫秒
        ctx.durationTime = (audioContext.duration * 1000).toFixed(0)
      })
      // audioContext.autoplay = false
      
    },
    // 监听数据
    spyAudioData(ctx) {
      // 1.监听播放时间
      if(ctx.isFirstPlay) {
        ctx.isFirstPlay = false
        audioContext.onTimeUpdate(() => {
          // 将秒转换为毫秒
          ctx.currentTime = (audioContext.currentTime * 1000).toFixed(0)
          // 设置进度条数值
          ctx.sliderValue = ((ctx.currentTime / ctx.durationTime) * 100).toFixed(0)
        })
      }
      const self = this
      // 2.监听歌曲播放完成
      audioContext.onEnded(() => {
        this.dispatch("changeSong")
      })
      // 3.监听歌曲是否播放或者暂停
      audioContext.onPause(() => {
        ctx.playerState = false
      })
      audioContext.onPlay(() => {
        ctx.playerState = true
      })
    },
    // 修改播放进度
    changeProgress(ctx, value) {
      let second, time
      // 如果value未定义，即：直接用当前时间修改当前歌词即可
      if(!value) {
        time = (audioContext.currentTime * 1000).toFixed(0)
        this.dispatch("changeLyric", time)
        return 
      }
      second = parseFloat(((value / 100) * (audioContext.duration)).toFixed(3))
      time = second * 1000
      // 在歌曲改变前，先改歌词
      this.dispatch("changeLyric", time)
      audioContext.seek(second)
    },
    // 修改歌词
    changeLyric(ctx, time) {
      for(let i = 0; i < ctx.lyric.length; i++) {
        if(time < ctx.lyric[i].time) {
          ctx.lyricIndex = i - 1
          break 
        }
        if(i == ctx.lyric.length - 1)
          ctx.lyricIndex = i
      }
    },
    // 修改播放状态
    changePlayState(ctx) {
      // 如果本来是暂停的，则播放，反之同理
      if(ctx.playerState) {
        audioContext.pause()
      } else {
        audioContext.play()
      }
      ctx.playerState = !ctx.playerState
    },
    // 修改播放模式
    changePlayerMode(ctx) {
      ctx.playerMode = (ctx.playerMode + 1) % 3
    },
    // 下一首、上一首、重新播放
    changeSong(ctx, next = true, restart = false) {
      // 如果为重新播放，则执行
      if(restart) {
        ctx.songData = ctx.songList[ctx.songIndex]
        this.dispatch("initSong", ctx.songData.id)
        return
      }
      const length = ctx.songList.length
      switch(ctx.playerMode) {
        // 1.循环播放
        case 0:
          // 1.1 下一首
          if(next)
            ctx.songIndex = (ctx.songIndex + 1) % length
          // 1.2 上一首
          else 
            ctx.songIndex = (ctx.songIndex - 1 + length) % length
          ctx.songData = ctx.songList[ctx.songIndex]
          this.dispatch("initSong", ctx.songData.id)
          break;
        // 2.单曲循环
        case 1:
          this.dispatch("changeProgress", 0) // 重新播放
          break;
        // 3.随机播放
        case 2:
          ctx.songIndex = (Math.random() * length).toFixed(0)
          ctx.songData = ctx.songList[ctx.songIndex]
          this.dispatch("initSong", ctx.songData.id)
          break;
        default:
          break;
      }
    },
    // 从歌曲列表中移除一首歌
    removeSong(ctx, index) {
      let songList = []
      for(let i = 0; i < ctx.songList.length; i++) {
        if(index == i)
          continue
        songList.push(ctx.songList[i])
      }
      ctx.songList = songList
      // 如果移除的是当前播放的歌曲，那么直接下一首
      if(index == ctx.songIndex){
        this.dispatch("changeSong", false, true)
      }
    }
  },
})

export {
  playerStore
}
